﻿using NModbus;
using System;
using System.Collections.Concurrent;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;

namespace AnalogInput
{
    public class ModbusTcpHelperJy
    {
        public string Address { get; set; }
        public int Port { get; set; }
        public int Timeout { get; set; } = 3000;
        private IModbusMaster master;
        CancellationTokenSource cansrc = new CancellationTokenSource();
        public static event Action<ConcurrentDictionary<int, float>> AnalogEvent;
        private ConcurrentDictionary<int, float> pairs = new ConcurrentDictionary<int, float>();
        private string part;
        public ModbusTcpHelperJy() { }
        public ModbusTcpHelperJy(string ip, int port)
        {
            Address = ip;
            Port = port;
        }
        /// <summary>
        /// 准备就绪
        /// </summary>
        public async void Ready(ushort startAdr, ushort numRegisters, byte slaveAdr)
        {
            const int retryDelayMilliseconds = 2000;
            const int maxRetries = int.MaxValue;
            int retryCount = 0;
            await Task.Factory.StartNew(async () =>
            {
                while (!cansrc.IsCancellationRequested)
                {
                    try
                    {
                        using (TcpClient tcpClient = new TcpClient(Address, Port))
                        {
                            ModbusFactory factory = new ModbusFactory();
                            master = factory.CreateMaster(tcpClient);
                            master.Transport.ReadTimeout = Timeout;
                            await ReadDataAsync(master, startAdr, numRegisters, slaveAdr);
                            retryCount = 0;
                        }
                        Thread.Sleep(50);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"Error reading Modbus data at {DateTime.Now}: {ex.Message}");
                        retryCount++;
                        if (retryCount >= maxRetries)
                        {
                            Console.WriteLine($"Failed to read Modbus data after {maxRetries} attempts. Exiting loop");
                            break;
                        }
                        await Task.Delay(retryDelayMilliseconds);
                    }
                }
            });

        }
        /// <summary>
        /// 停止监控
        /// </summary>
        public void Stop()
        {
            cansrc.Cancel();
        }
        /// <summary>
        /// 读取值
        /// </summary>
        /// <param name="master"></param>
        /// <returns></returns>
        private async Task ReadDataAsync(IModbusMaster master, ushort startAdr, ushort numRegisters, byte slaveAdr)
        {
            try
            {
                pairs?.Clear();
                ushort startAddressAIN1 = startAdr;//0
                ushort numRegistersAIN1 = numRegisters;//32
                ushort[] ainData = await master.ReadHoldingRegistersAsync(slaveAdr, startAddressAIN1, numRegistersAIN1);//254 ReadInputRegistersAsync
                for (int i = 0; i < ainData.Length; i++)
                {
                    pairs.TryAdd(i, /*ainData[i]*/(float)(ainData[i] * 0.001));
                }
                AnalogEvent?.Invoke(pairs);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        /// <summary>
        /// 写入值
        /// </summary>
        /// <param name="values">8个数据</param>
        /// <returns></returns>
        public async Task WriteValueAsync(ushort[] values)
        {
            await master.WriteMultipleRegistersAsync(1, 0, values);
        }
    }

}
